package com.fingard.dsp.bank.directbank.zyb02;

import java.math.BigDecimal;
import java.sql.Connection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.fingard.FGBiz;
import com.fingard.constant.DateFormat2;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.allinpay02.util.SybUtil;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.dsp.bank.reqrespobj.quotecheck.ReqAQ01BalQry;
import com.fingard.dsp.bank.reqrespobj.quotecheck.ReqAtsAQ01BalQry;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.net.IpHelper;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

public class ZYB02SinglePay extends ZYB02Base implements ISinglePay {

    public RetAtsSingle d_1908_SglPay_sameBank(ReqSingle p_req1908) throws Exception {
        String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
        //返回ATS的对象
        StringBuilder errMsg = new StringBuilder();
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        detail.reqSeqID = p_req1908.singleDetail.askNumber;
        //通用参数赋值
        ZYB02Header bankHeader = new ZYB02Header();
        //bankHeader.SEQ_NO = reqHeader.reqSeqID;
        //bankHeader.SEQ_NO = createBankSerialNumber(reqHeader.bankCode,reqHeader.transType,reqHeader.reqSeqID);
        bankHeader.SEQ_NO = seqNumberStart+reqHeader.reqSeqID;
        //<editor-fold desc="保存流水号和对账码的映射关系">
        String atsCheckCode = p_req1908.singleDetail.abstractATS;
        boolean result = saveCheckCode(bankHeader.SEQ_NO,atsCheckCode,errMsg);
        if(errMsg.length() > 0 || !result) {
            detail.respCode = "0";
            detail.respInfo = "保存流水号和对账码映射失败："+errMsg.toString();
            detail.reqSeqID = p_req1908.singleDetail.askNumber;
            detail.transState = PaymentState.FAIL_Payment;
            detail.payInfoCode = "保存流水号和对账码映射失败："+errMsg.toString();
            retAts.writeRetDetail(detail);
            return retAts;
        }
        //</editor-fold>
        bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "SAMEBANKSINGLEPAY");
        String transTime = p_req1908.reqHeader.transTime;
        bankHeader.TRAN_DATE = Format.Date10Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.TRAN_TIMESTAMP = TIME12FORMAT.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.USER_IP = getIpInfoMap(p_req1908.getOriReqXml()).get("userIP");
        bankHeader.SERVER_IP = getIpInfoMap(p_req1908.getOriReqXml()).get("serverIP");
        //发银行报文的XML对象
        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;

        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("Message");
        xmlWriter.writeStartElement("Head");
        xmlWriter.writeElementString("_TransactionId", bankHeader.TRAN_CODE);
        xmlWriter.writeElementString("_MCHTimestamp", bankHeader.TRAN_DATE+" "+bankHeader.TRAN_TIMESTAMP);
        xmlWriter.writeElementString("_MChannelId", getBankConfig().getMapValueByKey("Sys_Head", "CONSUMER_ID"));
        xmlWriter.writeElementString("_MCHJnlNo", bankHeader.SEQ_NO);
        xmlWriter.writeElementString("_AccessIp", bankHeader.USER_IP);
        xmlWriter.writeElementString("_AccessHost", bankHeader.USER_IP);
        xmlWriter.writeElementString("_ChannelIP", bankHeader.SERVER_IP);
        xmlWriter.writeElementString("_locale", getBankConfig().getMapValueByKey("ACROSSBANK","_locale"));
        xmlWriter.writeEndElement();

        xmlWriter.writeStartElement("Body");
        xmlWriter.writeElementString("PayerAcctNo", p_req1908.singleDetail.payAct);
        xmlWriter.writeElementString("PayerAcctName", p_req1908.singleDetail.payName);
        xmlWriter.writeElementString("OrgCode", p_req1908.singleDetail.payOrganizationCode);//组织机构代码证-ats那边的组织代码
        xmlWriter.writeElementString("PayeeAcctNo", p_req1908.singleDetail.recAct);
        xmlWriter.writeElementString("PayeeAcctName", p_req1908.singleDetail.recName);
        xmlWriter.writeElementString("TrsAmount", p_req1908.singleDetail.payAmount);
        //xmlWriter.writeElementString("TranNote", p_req1908.singleDetail.purpose);//用途
        //xmlWriter.writeElementString("Remark", p_req1908.singleDetail.memo);//备注

        //TranNote对应核心的交易事项(备注)TRAN_NOTE 这个字段不用 20181128
        //Remark对应核心的摘要NARRATIVE我们要放用途 20181128
        xmlWriter.writeElementString("Remark", p_req1908.singleDetail.purpose);
        xmlWriter.writeElementString("TranNote", p_req1908.singleDetail.memo);
        //<editor-fold desc="代码备份201810302300">
        //写入通用的头部节点
        //writeCommonHeader(xmlWriter, bankHeader);

        //<editor-fold desc="单笔付款业务字段">
        /*xmlWriter.writeElementString("TRAN_NOTE", p_req1908.singleDetail.purpose);
        xmlWriter.writeElementString("NARRATIVE", p_req1908.singleDetail.memo);
        xmlWriter.writeElementString("BASE_ACCT_NO", p_req1908.singleDetail.payAct);
        xmlWriter.writeElementString("CCY", convertCurToBank(p_req1908.singleDetail.payCur));
        xmlWriter.writeElementString("INPUT_BAL_TYPE", getBankConfig().getValueAsString("INPUT_BAL_TYPE"));
        xmlWriter.writeElementString("TRANSFER_MODE", getBankConfig().getValueAsString("TRANSFER_MODE"));
        xmlWriter.writeElementString("TRAN_AMT", p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("CHECK_OPTION", getBankConfig().getValueAsString("CHECK_OPTION"));

        xmlWriter.writeStartElement("TRAN_ARRAY");
        XElement row  = new XElement("Row","");
        row.addChild(new XElement("BASE_ACCT_NO",p_req1908.singleDetail.recAct));
        row.addChild(new XElement("TRAN_AMT",p_req1908.singleDetail.payAmount));
        row.addChild(new XElement("CCY",convertCurToBank(p_req1908.singleDetail.payCur)));
        row.addChild(new XElement("TRAN_TYPE",getBankConfig().getMapValueByKey("TRAN_TYPE","SAMEBANKSINGLEPAY")));
        row.addChild(new XElement("NARRATIVE",p_req1908.singleDetail.memo));
        row.addChild(new XElement("ACCT_NAME",p_req1908.singleDetail.recName));
        xmlWriter.writeXElement(row);
        xmlWriter.writeElementString("SERV_DETAIL", "");*/
        //</editor-fold>
        //</editor-fold>

        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();

        String[] retStrArr = sendXmlToBank(xmlWriter.toXmlString());

        if (retStrArr[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            XmlTextReader tmpBkReader = loadBankRespXmlReader(retStrArr[1], tmpSbMsg);

            if (tmpBkReader != null) {
                String tmpStatus = tmpBkReader.getFirstText("/Message/Head/_RejCode");
                String ret_msg = tmpBkReader.getFirstText("/Message/Head/_RejMsg");
                String ret_code = tmpBkReader.getFirstText("/Message/Head/_ProcessState");
                String tmpStatusText = tmpBkReader.getFirstText("/Message/Body/SeqNo");
                if(StringHelper.isNullOrEmpty(tmpStatusText)) {
                    detail.respCode = "0";
                    detail.respInfo = ret_msg;
                    detail.payInfoCode = tmpStatus+"-"+ret_msg;
                    detail.transState = ret_code;
                    detail.transAmt = p_req1908.singleDetail.payAmount;
                    retAts.writeRetDetail(detail);
                    return retAts;
                    //throw new Exception("银行没有返回支付流水号！");
                } else {
                    WriteBankLogLn("银行返回的流水号为："+tmpStatusText);
                    saveReqSeqIDMapping(p_req1908.reqHeader.bankCode,p_req1908.singleDetail.getPayDateTime(),bankHeader.SEQ_NO,tmpStatusText,errMsg);
                    //这里保存失败了也没关系，查询的时候先从表里查，没查到会再从银行查，所以不抛异常
                    /*if(errMsg.length() > 0) {
                        throw new Exception("保存银行流水号出错"+errMsg.toString());
                    }*/
                }
                detail.respCode = "0";
                detail.respInfo = ret_msg+"-"+tmpStatusText;
                detail.payInfoCode = tmpStatus+"-"+ret_msg+"-"+tmpStatusText;
                detail.transState = ret_code;
                detail.transAmt = p_req1908.singleDetail.payAmount;
                retAts.writeRetDetail(detail);
                return retAts;
            } else {
                retAts.writeStart();
                retAts.writeRespCode("-1");
                retAts.writeRespInfo(tmpSbMsg.toString());
            }
        } else if (retStrArr[0].equals(ConnState.FAIL)) {
            detail.respCode = "0";
            detail.respInfo = retStrArr[1];
            detail.reqSeqID = p_req1908.singleDetail.askNumber;
            detail.transState = PaymentState.FAIL_Payment;
            detail.payInfoCode = retStrArr[0]+"-"+detail.respInfo;
            retAts.writeRetDetail(detail);
        } else {
            retAts.writeStart();
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(retStrArr[1].toString());
        }
        retAts.writeEnd();
        return retAts;
    }

    public RetAtsSingle d_1944_QrySglPay_sameBank(ReqQrySingle p_req1944) throws Exception {
        String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        //通用参数赋值
        ZYB02Header bankHeader = new ZYB02Header();
        //bankHeader.SEQ_NO = reqHeader.transSeqID;
        //StringBuilder errMsg = new StringBuilder();
        bankHeader.SEQ_NO = seqNumberStart+reqHeader.transSeqID;
        /*if(errMsg.length() > 0) {
            throw new Exception("查找银行流水号失败！");
        }*/
        bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "SAMEBANKSINGLEPAYQUERY");
        String transTime = p_req1944.reqHeader.transTime;
        bankHeader.TRAN_DATE = Format.Date8Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.TRAN_TIMESTAMP = Format.Time9Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.USER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("userIP");
        bankHeader.SERVER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("serverIP");
        //发银行报文的XML对象
        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;
        //写入通用的头部节点
        writeCommonHeader(xmlWriter, bankHeader);
        StringBuilder errMsg = new StringBuilder();
        String channel_seq_no = "";
        channel_seq_no = getBankSerinalNum(seqNumberStart+reqHeader.reqSeqID,DateHelper.convertToDateExtra(p_req1944.bgnDate),errMsg);
        if(StringHelper.isNullOrEmpty(channel_seq_no)) {
            WriteBankLogLn("从数据库里没有查询到银行流水号："+errMsg.toString());
            WriteBankLogLn("从数据库里没有查询到银行流水号，通过接口查开始...");
            channel_seq_no = getSerinalNumberFromBank(p_req1944,errMsg);
            if(StringHelper.isNullOrEmpty(channel_seq_no)) {
                throw new Exception("查询银行流水号失败："+errMsg.toString());
            } else {
                if("查询为空".equals(errMsg.toString())) {
                    errMsg = errMsg.delete(0,errMsg.length());
                    WriteBankLogLn("查询得到的银行流水号为："+channel_seq_no);
                    boolean result = saveReqSeqIDMapping(p_req1944.reqHeader.bankCode,p_req1944.getBgnDateTime(),seqNumberStart+reqHeader.reqSeqID,channel_seq_no,errMsg);
                    if(errMsg.length() > 0 || !result) {//保存流水号映射关系失败，返回银行处理中
                        retDetail.reqSeqID = p_req1944.askNumber;
                        retDetail.respCode = "0";
                        retDetail.respInfo = "保存流水号失败，请稍后查询";
                        retDetail.payInfoCode = "保存流水号失败，请稍后查询";
                        retDetail.transState = "UC";
                        retAts.writeRetDetail(retDetail);
                        return retAts;
                    }
                }
            }
        }
        xmlWriter.writeElementString("CHANNEL_SEQ_NO", channel_seq_no);

        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();

        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String bankSeqNo = tmpBkReader.getFirstText("/Reply_Msg/Body/CHANNEL_SEQ_NO");
                    //返回流水号校验
                    /*String source_reference = getBankSerinalNum(seqNumberStart+p_req1944.askNumber,DateHelper.convertToDateExtra(p_req1944.bgnDate),errMsg);
                    if(errMsg.length() > 0) {
                        throw new Exception(errMsg.toString());
                    }*/
                    if(StringHelper.isNullOrEmpty(bankSeqNo) || !channel_seq_no.equals(bankSeqNo)) {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = tmpStrRet[1];
                        retAts.writeRetDetail(retDetail);
                        return retAts;
                    }

                    String status = tmpBkReader.getFirstText("/Reply_Msg/Body/STATUS");
                    String err_code = tmpBkReader.getFirstText("/Reply_Msg/Body/ERROR_CODE");
                    String err_msg = tmpBkReader.getFirstText("/Reply_Msg/Body/ERROR_MSG");
                    if (status != null && status.equals(TMPSTATUS)) {
                        retDetail.reqSeqID = p_req1944.askNumber;
                        retDetail.respCode = "0";
                        retDetail.respInfo = err_msg;
                        retDetail.payInfoCode = err_code+"-"+err_msg;
                        retDetail.transState = err_code;
                    } else {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = err_code + "-" + err_msg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retDetail.respCode = "-1";
            retDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }

        retAts.writeRetDetail(retDetail);
        return retAts;
    }

    public RetAtsSingle d_1908_SglPay_acrossBank(ReqSingle p_req1908) throws Exception {
        String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        StringBuilder errMsg = new StringBuilder();
        RetAtsSglDetail detail = new RetAtsSglDetail();
        detail.reqSeqID = p_req1908.singleDetail.askNumber;
        //通用参数赋值
        ZYB02Header bankHeader = new ZYB02Header();
        bankHeader.SEQ_NO = seqNumberStart+reqHeader.reqSeqID;
        //<editor-fold desc="保存流水号和对账码的映射关系">
        String atsCheckCode = p_req1908.singleDetail.abstractATS;
        boolean result = saveCheckCode(bankHeader.SEQ_NO,atsCheckCode,errMsg);
        if(errMsg.length() > 0 || !result) {
            detail.respCode = "0";
            detail.respInfo = "保存流水号和对账码映射失败："+errMsg.toString();
            detail.reqSeqID = p_req1908.singleDetail.askNumber;
            detail.transState = PaymentState.FAIL_Payment;
            detail.payInfoCode = "保存流水号和对账码映射失败："+errMsg.toString();
            retAts.writeRetDetail(detail);
            return retAts;
        }
        //</editor-fold>
        bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "ACROSSBANKSINGLEPAY");
        String transTime = p_req1908.reqHeader.transTime;
        bankHeader.TRAN_DATE = Format.Date10Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.TRAN_TIMESTAMP = TIME12FORMAT.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.USER_IP = getIpInfoMap(p_req1908.getOriReqXml()).get("userIP");
        bankHeader.SERVER_IP = getIpInfoMap(p_req1908.getOriReqXml()).get("serverIP");
        //发银行报文的XML对象
        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;
        //写入通用的头部节点
        //<editor-fold desc="Head头部字段处理">
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("Message");
        xmlWriter.writeStartElement("Head");
        xmlWriter.writeElementString("_TransactionId", bankHeader.TRAN_CODE);
        xmlWriter.writeElementString("_MCHTimestamp", bankHeader.TRAN_DATE + " " + bankHeader.TRAN_TIMESTAMP);
        xmlWriter.writeElementString("_MChannelId", getBankConfig().getMapValueByKey("Sys_Head", "CONSUMER_ID"));
        xmlWriter.writeElementString("_DeptSeq", getBankConfig().getMapValueByKey("ACROSSBANK","_DeptSeq"));
        xmlWriter.writeElementString("_DeptId", getBankConfig().getMapValueByKey("ACROSSBANK","_DeptId"));
        xmlWriter.writeElementString("_MCHJnlNo", bankHeader.SEQ_NO);
        xmlWriter.writeElementString("_AccessIp", bankHeader.USER_IP);
        xmlWriter.writeElementString("_AccessHost", bankHeader.USER_IP);
        xmlWriter.writeElementString("_ChannelIP", bankHeader.SERVER_IP);
        xmlWriter.writeElementString("_locale", getBankConfig().getMapValueByKey("ACROSSBANK","_locale"));
        xmlWriter.writeEndElement();
        //</editor-fold>
        //<editor-fold desc="Body报文体字段处理">
        xmlWriter.writeStartElement("Body");
        XElement PayerAccount = new XElement("PayerAccount", "");
        PayerAccount.addChild(new XElement("No", p_req1908.singleDetail.payAct));
        xmlWriter.writeXElement(PayerAccount);
        XElement PayerCurrency = new XElement("PayerCurrency", "");
        PayerCurrency.addChild(new XElement("Code", convertCurToBank(p_req1908.singleDetail.payCur)));
        xmlWriter.writeXElement(PayerCurrency);
        XElement PayeeAccount = new XElement("PayeeAccount", "");
        PayeeAccount.addChild(new XElement("No", p_req1908.singleDetail.recAct));
        xmlWriter.writeXElement(PayeeAccount);
        XElement PayeeCurrency = new XElement("PayeeCurrency", "");
        PayeeCurrency.addChild(new XElement("Code", convertCurToBank(p_req1908.singleDetail.recCur)));
        xmlWriter.writeXElement(PayeeCurrency);
        xmlWriter.writeElementString("PayerAcName", p_req1908.singleDetail.payName);
        xmlWriter.writeElementString("PayeeAcName", p_req1908.singleDetail.recName);
        XElement TrsCurrency = new XElement("TrsCurrency", "");
        TrsCurrency.addChild(new XElement("Code", convertCurToBank(p_req1908.singleDetail.recCur)));
        TrsCurrency.addChild(new XElement("CRFlag", getBankConfig().getMapValueByKey("ACROSSBANK","CRFlag")));
        xmlWriter.writeXElement(TrsCurrency);
        xmlWriter.writeElementString("TrsAmount", p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("Remark", p_req1908.singleDetail.purpose);
        //AttachInfo--备注  FundUsage--附言
        //xmlWriter.writeElementString("AttachInfo", p_req1908.singleDetail.memo);
        //xmlWriter.writeElementString("FundUsage", p_req1908.singleDetail.purpose);

        xmlWriter.writeElementString("PayeeBankClearId", p_req1908.singleDetail.cnapsCode);
        xmlWriter.writeElementString("PayeeBankId", p_req1908.singleDetail.recBankCode);
        xmlWriter.writeElementString("PayeeDeptId", p_req1908.singleDetail.cnapsCode);
        xmlWriter.writeElementString("PayerDeptId", p_req1908.singleDetail.payBankLocationCode);
        xmlWriter.writeElementString("PayeeBankName", p_req1908.singleDetail.recBankName);
        xmlWriter.writeElementString("PayeeDeptName", p_req1908.singleDetail.recBankLocation);

        /**
         * D 小额(工作日小于等于5万，节假日小于等于50万)
         * P 超网(小于等于5万)
         * C 大额(金额没有限制，时间有限制)ats那边会调用AQ01OtherElse查询大额支付系统是否开启，这里不用管时间
         *
         * 金额大于5万直接走大额系统C
         * 小于等于5万：加急-超网P,不加急-小额D
         */
        String trsMode = "";
        BigDecimal payAmount = new BigDecimal(p_req1908.singleDetail.payAmount);
        if(payAmount.compareTo(maxAmout) == 1) {
            trsMode = "C";
            //走大额时，判断大额是否开启，如查到明确开启则继续，其它情况一律切换为小额
            Boolean isPaymentSystemWork = isPaymentSystemWork();
            if(!isPaymentSystemWork) {
                trsMode = "D";
            }
        } else {
            if("1".equals(p_req1908.singleDetail.paySpd)) {//加急
                trsMode = "P";
            } else {//不加急
                trsMode = "D";
            }
        }

        xmlWriter.writeElementString("TrsMode", trsMode);
        xmlWriter.writeElementString("FeeFlag", getBankConfig().getMapValueByKey("ACROSSBANK","FeeFlag"));
        xmlWriter.writeElementString("OrgCode", p_req1908.singleDetail.payOrganizationCode);//组织机构代码证-ats那边的组织代码
        //</editor-fold>
        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();

        String[] retStrArr = sendXmlToBank(xmlWriter.toXmlString());

        if (retStrArr[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            XmlTextReader tmpBkReader = loadBankRespXmlReader(retStrArr[1], tmpSbMsg);

            if (tmpBkReader != null) {
                String tmpStatus = tmpBkReader.getFirstText("/Message/Head/_RejCode");
                String ret_msg = tmpBkReader.getFirstText("/Message/Head/_RejMsg");
                String ret_code = tmpBkReader.getFirstText("/Message/Head/_ProcessState");
                String tmpStatusText = tmpBkReader.getFirstText("/Message/Body/SeqNo");
                if(StringHelper.isNullOrEmpty(tmpStatusText)) {
                    detail.respCode = "0";
                    detail.respInfo = ret_msg;
                    detail.payInfoCode = tmpStatus+"-"+ret_msg;
                    detail.transState = ret_code;
                    detail.transAmt = p_req1908.singleDetail.payAmount;
                    retAts.writeRetDetail(detail);
                    return retAts;
                    //throw new Exception("银行没有返回支付流水号！");
                } else {
                    WriteBankLogLn("银行返回的流水号为："+tmpStatusText);
                    saveReqSeqIDMapping(p_req1908.reqHeader.bankCode,p_req1908.singleDetail.getPayDateTime(),bankHeader.SEQ_NO,tmpStatusText,errMsg);
                    //这里保存失败了也没关系，查询的时候表里没有会从银行查，所以不抛异常
                    /*if(errMsg.length() > 0) {
                        throw new Exception("保存银行流水号出错"+errMsg.toString());
                    }*/
                }
                detail.respCode = "0";
                detail.respInfo = ret_msg+"-"+tmpStatusText;
                detail.payInfoCode = tmpStatus+"-"+ret_msg+tmpStatusText;
                detail.transState = ret_code;
                detail.transAmt = p_req1908.singleDetail.payAmount;
                retAts.writeRetDetail(detail);
                return retAts;
            } else {
                retAts.writeStart();
                retAts.writeRespCode("-1");
                retAts.writeRespInfo(tmpSbMsg.toString());
            }
        } else if (retStrArr[0].equals(ConnState.FAIL)) {
            detail.respCode = "0";
            detail.respInfo = retStrArr[1];
            detail.reqSeqID = p_req1908.singleDetail.askNumber;
            detail.transState = PaymentState.FAIL_Payment;
            detail.payInfoCode = retStrArr[0]+"-"+detail.respInfo;
            retAts.writeRetDetail(detail);
        } else {
            retAts.writeStart();
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(retStrArr[1].toString());
        }
        retAts.writeEnd();
        return retAts;
    }

    public RetAtsSingle d_1944_QrySglPay_acrossBank(ReqQrySingle p_req1944) throws Exception {
        String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        //通用参数赋值
        ZYB02Header bankHeader = new ZYB02Header();
        //bankHeader.SEQ_NO = reqHeader.transSeqID;
        bankHeader.SEQ_NO = seqNumberStart+reqHeader.transSeqID;
        bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "ACROSSBANKSINGLEPAYQUERY");
        String transTime = p_req1944.reqHeader.transTime;
        bankHeader.TRAN_DATE = Format.Date8Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.TRAN_TIMESTAMP = Format.Time9Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.USER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("userIP");
        bankHeader.SERVER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("serverIP");
        //发银行报文的XML对象
        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;
        //写入通用的头部节点
        writeCommonHeader(xmlWriter, bankHeader);

        xmlWriter.writeStartElement("TRAN_ARRAY");
        XElement row  = new XElement("Row","");
        StringBuilder errMsg = new StringBuilder();

        String source_reference = "";
        source_reference = getBankSerinalNum(seqNumberStart+reqHeader.reqSeqID,DateHelper.convertToDateExtra(p_req1944.bgnDate),errMsg);
        if(StringHelper.isNullOrEmpty(source_reference)) {
            WriteBankLogLn("从数据库里没有查询到银行流水号："+errMsg.toString());
            WriteBankLogLn("从数据库里没有查询到银行流水号，通过接口查开始...");
            source_reference = getSerinalNumberFromBank(p_req1944,errMsg);
            if(StringHelper.isNullOrEmpty(source_reference)) {
                throw new Exception("查询银行流水号失败："+errMsg.toString());
            } else {
                if("查询为空".equals(errMsg.toString())) {
                    errMsg = errMsg.delete(0,errMsg.length());
                    WriteBankLogLn("查询得到的银行流水号为："+source_reference);
                    boolean result = saveReqSeqIDMapping(p_req1944.reqHeader.bankCode,p_req1944.getBgnDateTime(),seqNumberStart+reqHeader.reqSeqID,source_reference,errMsg);
                    if(errMsg.length() > 0 || !result) {//保存流水号映射关系失败，返回银行处理中
                        retDetail.reqSeqID = p_req1944.askNumber;
                        retDetail.respCode = "0";
                        retDetail.respInfo = "保存流水号失败，请稍后查询";
                        retDetail.payInfoCode = "保存流水号失败，请稍后查询";
                        retDetail.transState = "UC";
                        retAts.writeRetDetail(retDetail);
                        return retAts;
                    }
                }
            }
        }
        /*String source_reference = getSerinalNumberFromBank(p_req1944,errMsg);
        if(errMsg.length() > 0) {
            throw new Exception(errMsg.toString());
        }*/
        row.addChild(new XElement("SOURCE_REFERENCE",source_reference));
        xmlWriter.writeXElement(row);

        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();

        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpStatus = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_STATUS");
                    String ret_code = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_ARRAY/Row/RET_CODE");
                    String tmpStatusText = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_ARRAY/Row/RET_MSG");
                    String pay_state = tmpBkReader.getFirstText("/Reply_Msg/Body/DETAIL_INFO/Row/STATUS");
                    String channel_seq_no = tmpBkReader.getFirstText("/Reply_Msg/Body/DETAIL_INFO/Row/SOURCE_REFERENCE");
                    //流水号校验
                    if(StringHelper.isNullOrEmpty(channel_seq_no) || !source_reference.equals(channel_seq_no)) {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = "银行返回的流水号有误！";
                        retAts.writeRetDetail(retDetail);
                        return retAts;
                    }

                    if (tmpStatus != null && tmpStatus.equals(TMPSTATUS)) {
                        if(pay_state != null) {
                            retDetail.reqSeqID = p_req1944.askNumber;
                            retDetail.respCode = "0";
                            retDetail.respInfo = tmpStatusText;
                            retDetail.payInfoCode = ret_code+"-"+tmpStatusText;
                            retDetail.transState = pay_state;
                        } else {
                            retDetail.respCode = "-1";
                            retDetail.respInfo = ret_code + "-" + tmpStatusText;
                        }
                    } else {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = tmpStatus + "-" + tmpStatusText;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retDetail.respCode = "-1";
            retDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }

        retAts.writeRetDetail(retDetail);
        return retAts;
    }

    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        if (p_req1908.singleDetail.sameBnk.equals("1")) {//同行
            return d_1908_SglPay_sameBank(p_req1908);
        } else {//跨行
            return d_1908_SglPay_acrossBank(p_req1908);
        }
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        if (p_req1944.sameBnk.equals("1")) {//同行
            return d_1944_QrySglPay_sameBank(p_req1944);
        } else {//跨行
            return d_1944_QrySglPay_acrossBank(p_req1944);
        }
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }

    private boolean saveReqSeqIDMapping(String p_bankCode, Date p_transDate, String p_atsSeqID, String p_toBankSeqID, StringBuilder p_sb) {
        if (FGBiz.dspCenter.dspSet.dbConnectionSet != null) {
            try {
                Connection dbConn = null;
                try {
                    dbConn = getDbConnection();
                    JDBCHelper.update(dbConn, "insert into REQSEQIDMAPPING(URID,TRANSDATE,REQSEQID,BANKREQSEQID,BANKCODE)values(?,?,?,?,?)", new Object[]{p_atsSeqID, Format.Date10Format.format(p_transDate), p_atsSeqID, p_toBankSeqID, p_bankCode});
                    return true;
                } catch (Exception ex) {
                    p_sb.append(LogHelper.getStackTrace(ex));
                    ex.printStackTrace();
                } finally {
                    if (dbConn != null) {
                        dbConn.close();
                    }
                }
            } catch (Exception ex) {
                p_sb.append(LogHelper.getStackTrace(ex));
                ex.printStackTrace();
            }
        } else {
            p_sb.append("数据库连接未配置或有误");
        }
        return false;
    }

    private boolean saveCheckCode(String p_atsSeqID,String checkCode,StringBuilder errMsg) {
        if (FGBiz.dspCenter.dspSet.dbConnectionSet != null) {
            try {
                Connection dbConn = null;
                try {
                    dbConn = getDbConnection();
                    JDBCHelper.update(dbConn, "insert into UNIQUEID(KEYNAME,KEYVALUE,ROWVERSION)values(?,?,?)", new Object[]{p_atsSeqID, checkCode, 1});
                    return true;
                } catch (Exception ex) {
                    errMsg.append(LogHelper.getStackTrace(ex));
                    ex.printStackTrace();
                } finally {
                    if (dbConn != null) {
                        dbConn.close();
                    }
                }
            } catch (Exception ex) {
                errMsg.append(LogHelper.getStackTrace(ex));
                ex.printStackTrace();
            }
        } else {
            errMsg.append("数据库连接未配置或有误");
        }
        return false;
    }

    private String getBankSerinalNum(String REQSEQID,Date p_transDate,StringBuilder errMsg) {
        if (FGBiz.dspCenter.dspSet.dbConnectionSet != null) {
            try {
                Connection dbConn = null;
                try {
                    dbConn = getDbConnection();
                    Map<String, Object> reqSeqIDMap = JDBCHelper.execQuerySingle(dbConn, "select BANKREQSEQID from REQSEQIDMAPPING where TRANSDATE=? and REQSEQID=?", new Object[]{Format.Date10Format.format(p_transDate), REQSEQID});
                    if (reqSeqIDMap != null && reqSeqIDMap.size() > 0) {
                        return String.valueOf(reqSeqIDMap.get("BANKREQSEQID"));
                    }
                    errMsg.append("查询为空");
                } catch (Exception ex) {
                    errMsg.append(LogHelper.getStackTrace(ex));
                    ex.printStackTrace();
                } finally {
                    if (dbConn != null) {
                        dbConn.close();
                    }
                }
            } catch (Exception ex) {
                errMsg.append(LogHelper.getStackTrace(ex));
                ex.printStackTrace();
            }
        } else {
            errMsg.append("数据库连接未配置或有误");
        }
        return "";
    }

    private String getSerinalNumberFromBank(ReqQrySingle p_req1944,StringBuilder errMsg) throws Exception {
        WriteBankLogLn("查询全局流水号开始...");
        String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
        ZYB02Header bankHeader = new ZYB02Header();
        bankHeader.SEQ_NO = seqNumberStart+reqHeader.transSeqID+SybUtil.getValidatecode(2);
        bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "REQNUMBERQUERY");
        String transTime = p_req1944.reqHeader.transTime;
        bankHeader.TRAN_DATE = Format.Date10Format.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.TRAN_TIMESTAMP = TIME12FORMAT.format(DateHelper.convertToDateExtra(transTime));
        bankHeader.USER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("userIP");
        bankHeader.SERVER_IP = getIpInfoMap(p_req1944.getOriReqXml()).get("serverIP");
        //发银行报文的XML对象
        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;
        writeCommon(xmlWriter, bankHeader);

        xmlWriter.writeElementString("MchJnlNo",seqNumberStart+reqHeader.reqSeqID);
        //xmlWriter.writeElementString("MchJnlNo","MBC"+reqHeader.reqSeqID);
        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();

        String[] retStrArr = sendXmlToBank(xmlWriter.toXmlString());

        if (retStrArr[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            XmlTextReader tmpBkReader = loadBankRespXmlReader(retStrArr[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String seqNo = tmpBkReader.getFirstText("/Message/Body/SeqNo");
                if(StringHelper.hasAnyChar(seqNo)) {
                    WriteBankLogLn("查询到的全局流水号为："+seqNo);
                    return seqNo;
                } else {
                    errMsg.append(retStrArr[1]);
                }
            } else {
                errMsg.append(tmpSbMsg+":"+retStrArr[1]);
            }
        } else {
            errMsg.append(retStrArr[1]);
        }
        WriteBankLogLn("查询全局流水号结束...");
        return null;
    }

    private Boolean isPaymentSystemWork() {
        WriteBankLogLn("查询大额系统是否开启开始.....");
        //如查到明确开启则返回true，其它情况一律返回false
        try {
            String seqNumberStart = getBankConfig().getMapValueByKey("Sys_Head","CONSUMER_ID")+reqHeader.corporation;
            ZYB02Header bankHeader = new ZYB02Header();
            bankHeader.SEQ_NO = seqNumberStart+reqHeader.transSeqID;
            bankHeader.TRAN_CODE = getBankConfig().getMapValueByKey("TRANS_CODE", "QUERYBANKISWORKING");
            bankHeader.TRAN_DATE = Format.Date8Format.format(new Date());
            bankHeader.TRAN_TIMESTAMP = Format.Time9Format.format(new Date());
            //这里的查询大额是否开启是DSP这边发起的，并不是用户发起的，所以IP都是DSP
            bankHeader.USER_IP = IpHelper.getLocalHostIp();
            bankHeader.SERVER_IP = IpHelper.getLocalHostIp();
            //发银行报文的XML对象
            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.autoFormat = false;
            //写入通用的头部节点
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.insertIntoTag("CURRENT_NUM", "-1");
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String ret_status = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_STATUS");
                    String ret_code = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_ARRAY/Row/RET_CODE");
                    String ret_msg = tmpBkReader.getFirstText("/Reply_Msg/Sys_Head/RET_ARRAY/Row/RET_MSG");
                    if(TMPSTATUS.equals(ret_status) && RET_CODE.equals(ret_code)) {
                        while (tmpBkReader.read("/Reply_Msg/Body/SYS_STATUS/Row")) {
                            String format = tmpBkReader.readedXElement.getSingleText("FORMAT");
                            String login_status = tmpBkReader.readedXElement.getSingleText("LOGIN_STATUS");
                            String status = tmpBkReader.readedXElement.getSingleText("STATUS");
                            if("HVPS".equals(format)) {
                                if("3".equals(login_status)&&"10".equals(status)) {
                                    WriteBankLogLn("查询大额系统是否开启结束，查询结果为：开启");
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            WriteBankLogLn("查询大额系统是否开启结束，查询结果为：结果未知，支付渠道将切换为小额");
            //saas那边支付的时候也会查询大额系统是否开启，如果未开启，会查小额限额，超限额不允许支付。所以到了DSP这里小额渠道不用判断金额是否超限了。
            return false;
        } catch (Exception e) {
            WriteBankLogLn("查询大额系统是否开启异常(将切换为小额继续支付)："+e.getMessage());
            return false;
        }
    }
}
